﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using Android.App;
using Android.Content;
using Android.Graphics;
using Android.OS;
using Android.Runtime;
using Android.Util;
using Android.Views;

namespace StoveTop
{
	public class TimerView : View
	{
		public enum Color
		{
			Blue,
			Green,
			Yellow,
			Red
		};

		// Stroke and fill of the timer
		// Stroke is the outer edge, fill is the 'pie wedge'
		private Paint stroke;
		private Paint fill;
		private Paint innerFill;
		private Paint textFill;
		// Internals used to render the timer
		private RectF timerRect;
		private float textBoundSize;
		private int textYOffset;
		private int radius;
		private int innerRadius;
		private int x;
		private int y;
		private int thickness;
		// Internals that can be set externally to change the timer
		private int timerAngle;
		private string timerText;

		public TimerView (Context context) :
			base (context)
		{
			this.Initialize ();
		}

		public TimerView (Context context, IAttributeSet attrs) :
			base (context, attrs)
		{
			this.Initialize ();
		}

		public TimerView (Context context, IAttributeSet attrs, int defStyle) :
			base (context, attrs, defStyle)
		{
			this.Initialize ();
		}

		public void SetColor (Color color)
		{
			switch (color)
			{

			case Color.Blue:
				this.SetTimerColor (64, 192, 255);
				break;
			case Color.Green:
				this.SetTimerColor (64, 192, 64);
				break;
			case Color.Yellow:
				this.SetTimerColor (192, 192, 64);
				break;
			case Color.Red:
				this.SetTimerColor (192, 64, 64);
				break;

			}

			this.Invalidate ();
		}

		// Sets the slice of the timer that is visible (the animated portion)
		public void SetVisibleAngle(int angle)
		{
			this.timerAngle = angle;
			this.Invalidate ();
		}

		// Sets the text in the center of the timer
		public void SetText(string text)
		{
			this.timerText = text;
			this.UpdateTextSize ();
			this.Invalidate ();
		}

		// Resize the timer and all drawing elements
		protected override void OnSizeChanged (int w, int h, int oldw, int oldh)
		{
			base.OnSizeChanged (w, h, oldw, oldh);

			this.thickness = Math.Min (w, h) / 20;
			this.radius = (Math.Min (w, h) - this.thickness) / 2;
			this.innerRadius = this.radius / 2;

			this.x = w / 2;
			this.y = h / 2;

			this.timerRect = new RectF (
				this.x - this.radius + this.thickness, 
				this.y - this.radius + this.thickness, 
				this.x + this.radius - this.thickness, 
				this.y + this.radius - this.thickness);

			this.textBoundSize = 1.414214f * this.innerRadius;
			this.stroke.StrokeWidth = this.thickness;

			this.UpdateTextSize ();
		}

		protected override void OnDraw (Canvas canvas)
		{
			base.OnDraw (canvas);

			canvas.DrawCircle (this.x, this.y, this.radius - 1, this.innerFill);
			canvas.DrawCircle (this.x, this.y, this.radius, this.stroke);
			canvas.DrawArc (this.timerRect, -90, this.timerAngle, true, this.fill);
			canvas.DrawCircle (this.x, this.y, this.innerRadius, this.innerFill);
			canvas.DrawText (this.timerText, this.x, this.y + this.textYOffset, this.textFill);
		}

		private void Initialize ()
		{
			this.timerAngle = 0;
			this.timerText = string.Empty;
			this.timerRect = new RectF ();

			this.stroke = new Paint (PaintFlags.AntiAlias);
			this.fill = new Paint (PaintFlags.AntiAlias);
			this.innerFill = new Paint (PaintFlags.AntiAlias);
			this.textFill = new Paint (PaintFlags.AntiAlias);

			this.stroke.SetStyle (Paint.Style.Stroke);
			this.fill.SetStyle (Paint.Style.Fill);
			this.innerFill.SetStyle (Paint.Style.Fill);
			this.textFill.SetStyle (Paint.Style.Fill);
			this.textFill.SetTypeface (Typeface.Default);
			this.textFill.TextAlign = Paint.Align.Center;
		}

		private void SetTimerColor (int r, int g, int b)
		{
			this.fill.SetARGB (255, r, g, b);
			this.stroke.SetARGB (255, (int)(r * .75), (int)(g * .75), (int)(b * .75));
			this.textFill.SetARGB (255, (int)(r * .75), (int)(g * .75), (int)(b * .75));
			this.innerFill.SetARGB (255, 0, 0, 0);
		}

		private void UpdateTextSize ()
		{
			// --- begin nabbed from stackoverflow

			// Get the bounds of the text, using a test text size
			this.textFill.TextSize = 48f;

			Rect bounds = new Rect ();
			this.textFill.GetTextBounds (this.timerText, 0, this.timerText.Length, bounds);

			if (!bounds.IsEmpty)
			{
				// Calculate the desired size as a proportion of our test text size
				// Ensures text fits a specified width
				if (bounds.Width () > bounds.Height ())
				{
					this.textFill.TextSize = 48f * this.textBoundSize / bounds.Width ();
				}
				else
				{
					this.textFill.TextSize = 48f * this.textBoundSize / bounds.Height ();
				}

				// --- end nabbed from stackoverflow

				// Calculate the required offset to vertically center the text
				this.textFill.GetTextBounds (this.timerText, 0, this.timerText.Length, bounds);
				this.textYOffset = bounds.Height () / 2;
			}
		}
	}
}

